Skip to content

Refactor DSHX to profile-owned Codex TUI surface - #17

Draft
code-new-bie wants to merge 60 commits into
mainfrom
refactor/plugin-compliance-slim
Draft

code-new-bie wants to merge 60 commits into
mainfrom
refactor/plugin-compliance-slim

Conversation

@code-new-bie

@code-new-bie code-new-bie commented Aug 27, 2026 •

Copy link
Copy Markdown
Owner

Refactors DSHX into a standard DeepSeek Harness TUI surface bundle whose only product runtime is the user's official DSH profile/composition.

Final architecture:

  • dshx is a thin UX alias that ensures the bundle is installed, then launches official dsh --profile tui
  • Cordis mounts dshx-startup and dshx-presentation inside that existing composition
  • the profile-owned presentation row launches the pinned Codex TUI only
  • DSHX protocol uses anonymous directional inherited pipes between the mounted presentation adapter and the TUI; there is no UDS/WebSocket listener, bridge process, second Harness composition, or TUI-owned backend child
  • DSH remains authoritative for Agent, Session, Tool, Approval, Model, Skill/Subagent, sandbox/permission and persistence semantics
  • Codex code is a presentation-only thin fork; DSH semantics are projected into the pinned Codex wire/UI shapes

Exact candidate: 3729f2a6e5dc6422a21875e86c64ebac3fb95297.

The final delta from the previously green a7430794... candidate is .gitattributes forcing package-lock.json to eol=lf, preserving reviewed lockfile byte identity across Windows/macOS/Linux so release provenance can require one exact sourceLockSha256.

Exact-SHA automated evidence is now green:

  • CI run 33184987198: Core / Node 24 and Linux pinned Codex TUI both success; frozen graph, DSH closure, unit/contract suite, ownership boundary, official profile lifecycle, native build, thin-fork invariants, official bundle activation and Linux PTY/CJK/resize all passed
  • RC Platform Gate run 33184987192: Windows pinned build + ConPTY/CJK and macOS pinned build + PTY/CJK/resize both success; platform summary success
  • strict packaging preflight run 33185259423: platform package, release-bundle activation, clean install without a second DSH runtime and provenance checks success
  • four-platform release-matrix preflight run 33185304658: Linux x64, Windows x64, macOS arm64 and macOS x64 each built, exercised the native terminal smoke, packaged, activated through official DSH and clean-installed; cross-platform provenance/checksum aggregation success
  • release/1.0-rc now points to this exact candidate SHA

No automated architecture/runtime/package blocker is currently known.

Remaining release blockers are intentionally external to source correctness:

  1. create a real prerelease tag (next expected: v1.0.0-rc.9) at the current release/1.0-rc head so the repository's tag-triggered Release workflow produces immutable RC artifacts under real release semantics; the currently connected GitHub tool does not expose Git-tag creation
  2. use that exact generated Windows RC artifact for issue 1.0 RC gate: Windows Terminal / CJK / IME side-by-side parity #12's Windows Terminal side-by-side and real Chinese IME compose/commit/cancel acceptance; ConPTY cannot prove IME behavior

This PR remains draft and must not be merged or promoted to stable v1.0.0 until #12–#15 satisfy their formal RC/tag closure rules. Do not solve any remaining release failure by introducing a shadow DSH runtime or weakening the ownership/security boundary.

code-new-bie and others added 30 commits August 25, 2026 21:20
…pter

Merge app-server-adapter -> product-adapter -> release-adapter inheritance
into a single DshxPresentationAdapter. Method bodies stay verbatim per
layer; base/product seams survive as explicit helpers so the former
super.* call order remains auditable, and the merged dispatch table keeps
release-layer routing first.

The ownership guard now forbids shadow fork/seed state on the unified
adapter while requiring subagent interruption to delegate through
ctx.subagents.interrupt (reading DSH's durable parentSession header stays
the sanctioned authority path). Ignore local .build/ and .upstream/
materialization workspaces.
src/protocol.mjs (deterministic protocol PoC), src/server.mjs (TCP
WebSocket stub) and the TCP stub entry leave the production source tree
for devtools/. bin/dshx-stub-local.mjs stays: it drives real-TUI smoke
through the production local-IPC topology. Packaging already shipped only
bin/dshx.mjs + src/cli + src/dsh + src/protocol(dir), so artifacts are
unchanged; the production src tree no longer carries dead protocol code.
Add src/dsh/presentation-plugin.mjs exporting the official plugin shape
(name / inject / Config / apply, named exports only): it starts the
packaged bridge + adapter transport against the already-booted
composition Context, publishes the endpoint as the dshxPresentation
service, and returns transport disposal to the Cordis root Fiber.

bootDshxPresentationRuntime() mounts that plugin through the Cordis
dynamic-plugin API; bin/dshx now consumes the provided service instead of
driving local-server imperatively, and root-fiber disposal stays the sole
teardown authority (transport close no longer disposes the runtime when
mounted as a plugin).

The surface lock moves from hardcoded arrays in runtime-boot to the
declarative cordis.patch.yml bundle patch, loaded through DSH's own
optional-patch loader and failing closed when missing.
Topology and launcher lifecycle now describe the dshx-presentation
Cordis plugin row, the declarative cordis.patch.yml surface lock, and
the devtools/ location of the development-only protocol fixtures.
CI-grade disks boot the composition well inside the hardcoded 20s/10s;
slow checkouts such as a WSL /mnt/c mount do not. DSHX_SMOKE_BOOT_TIMEOUT_MS
and DSHX_SMOKE_DISPOSE_TIMEOUT_MS now raise the bounds without touching
the script; defaults are unchanged.
…tui)

The package now declares dsh.bundle.patch -> ./cordis.patch.yml, whose
insert rows mount the surface through the official loader:

  - dshx-startup      resolves env/packaged defaults, provides dshxStartup
  - dshx-presentation injects dshxStartup, hosts the local IPC transport,
                      publishes dshxPresentation, returns the disposer

The imperative mounting channel is gone: no ctx.plugin() call, no
launcher-owned patch file, and boot() drops its bareModuleBaseUrl anchor so
row names resolve from the profile directory exactly like the official CLI
(the healed profiles/node_modules fallback covers in-box packages).

bin/dshx becomes a thin bootstrap over official machinery: it ensures the
selected profile carries this exact package version via
'dsh plugin --profile <p> add <root>' (idempotent), boots the composition,
and spawns the TUI against the provided endpoint; root-fiber disposal owns
teardown. doctor gains a 'Surface profile' gate and counts the two row
services among its required services.

Runtime host services move to peerDependencies (dual-listed for dev);
only leaf parser libs stay dependencies, preserving the single-instance
rule that keeps profile installs from shadowing healed symlinks.

scripts/verify-bundle-install.mjs proves the full chain end to end with
real tooling: npm pack -> dsh plugin add into a temp DSH_HOME ->
--dump-config row assertions -> loader activation with live transport ->
no stateful-runtime shadowing.
- src/dsh/profile-bootstrap.mjs owns the official-machinery bootstrap
  (dsh CLI resolution: DSHX_DSH_BIN override -> dependency-local lib/bin.js
  -> PATH; satisfaction = exact version AND bundle-layer membership;
  DSHX_SKIP_PROFILE_BOOTSTRAP=1 escape hatch). bin/dshx and runtime-smoke
  both use it, so the smoke script works against the tui surface profile.
- scripts/verify-bundle-install.mjs resolves dsh the same way and now runs
  in CI (linux-tui job) after the bridge build; core enables pnpm for the
  bootstrap-driven runtime-smoke step.
- Ownership guard tracks the bootstrap module instead of the launcher.
- README gains a Plugin usage section; RUNTIME-INTEGRATION lifecycle and
  doctor description reflect loader-mounted rows and the profile gate.
The peerDependency pin is declarative only — profile installs never
resolve peers, so a host running a different DSH release would fail with
mysterious API errors. dshxRuntimeProfile now reads the version of the
installation that will actually boot and fails loud with an actionable
message (supported line <-> found version) when they diverge. The
supported line's single source of truth is the manifest's
@deepseek-ai/dsh peerDependency.
The plugin spec carries no host-version gates and official bundles
declare peer ranges only. Keep the tested line as honest metadata
(manifest peer pin + warn-once at boot naming both versions), but
proceed on any installed release.
Product scope: replicate only Codex's TUI shell — everything else is DSH.
Make the codebase say so structurally:

  src/tui-protocol/
    shapes.mjs    wire-format dictionary (former codex-shapes)
    adapter.mjs   app-server method routing + projection orchestration

Domain modules under src/dsh keep DSH vocabulary; the ownership guard now
asserts the dictionary lives only in tui-protocol and that no codex-named
module returns to src/dsh. Residual lowercase field mappings inside domain
modules are gradual-cleanup items, tracked by the same guard's placement
checks.
- Staged release package keeps host services as peerDependencies and ships
  only leaf parser libraries as dependencies: profile installs stay free of
  stateful runtime copies (single-instance rule) and never trip pnpm's
  build-script gate (node-pty/koffi/protobufjs all live in the healed host
  closure instead).
- Shrinkwrap root records the staged peerDependencies.
- Accept both npm pack --json shapes (array pre-10, name-keyed object since
  scoped records) — the old packed[0] access broke every scoped release.
verify-bundle-install gains a release flavor: when dist/release carries a
packaged artifact, it installs that exact tarball into a fresh profile via
the official command and proves loader activation with zero environment
overrides — endpoint live, bridge resolved from the installed copy's own
dist/bin, no stateful runtime shadowing. DSHX_REQUIRE_RELEASE=1 turns the
missing-artifact skip into a failure for CI wiring. Probe runs as a real
file because the hmr row resolves process.argv[1]. Legacy test filenames
follow the modules into the tui-protocol naming.
… dialect

user-input, plan-presentation, session-fork, thread-title, history-pages
and skills are DSH->Codex view builders consumed only by the protocol
layer; they move under src/tui-protocol/ so src/dsh converges on true
domain concerns. token-usage and tool-presentation stay shared with the
domain-side thread-controller for now.
…metadata

Bare `dsh --profile tui` mounts the surface and waits passively; mirror
the official web surface's printUrl precedent so the state is always
visible instead of a silent hang. Root manifest gains its repository
field.
…bundle

After each platform tarball is built, run verify-bundle-install with
DSHX_REQUIRE_RELEASE=1: official install into a fresh profile, composed
tree assertions, loader activation with zero environment overrides, and
the single-instance rule — on Linux and Windows both.
Set CARGO_PROFILE_RELEASE_DEBUG=0 (user-overridable) and strip the copied
Unix binaries. The Linux TUI drops from 1.1GB to 222MB and the platform
tarball from 272MB to 85MB with identical behavior; Windows keeps its
debug symbols beside the exe as before.
The production launcher no longer imports or boots any harness build from
our package: bin/dshx bootstraps the surface profile via the official
plugin command, then spawns the user's own 'dsh --profile tui'. The
loader mounts our rows inside THAT installation, so credentials parsing,
service registries and every other harness behavior come from a single
build — the user's — eliminating the dual-build divergence this machine
demonstrated (system vs registry copies of the same version string).

Interactive attachment moved into the presentation row (opt-in via
DSHX_ATTACH set only by our launcher): raw-mode TUI turns Ctrl+C into a
key event, so the host's SIGINT handler never fires during interaction;
non-TTY contexts degrade gracefully to a passive endpoint with a visible
listening hint. local-server drops its runtime-boot import edge, keeping
row-module graphs free of package-side harness builds.

Adoptive compatibility stance: peerDependencies become an advisory floor
('>=0.1.0-rc.8', no upper bound); the exact tested line stays as an
explicit constant surfaced through a one-shot startup warning on any
other installed release.
…stic

Production launcher zero-imports harness builds: bootstrap the surface
profile via the official plugin command, then spawn the user's own
'dsh --profile tui'. Their installation composes everything, parses their
state files, and hosts our loader-mounted rows; the pinned TUI attaches
from inside the presentation row (opt-in DSHX_ATTACH from our launcher,
raw-mode Ctrl+C stays a key event; non-TTY degrades to a passive endpoint
with a visible listening hint).

dsh CLI resolution now prefers the user's PATH installation over the
dependency-local copy, and runtime-boot anchors composition/healing at
that same installation — eliminating the dual-build divergence this
machine demonstrated (system vs registry copies sharing one version
string, with incompatible credentials parsing).

Adoptive compatibility: peerDependencies become an advisory floor
('>=0.1.0-rc.8', unbounded); the exact tested line is an explicit
constant surfaced as a one-shot warning on other installed releases.
local-server drops its runtime-boot import edge so row graphs stay free
of package-side harness builds. doctor's harness gate now probes the
user's real installation instead of an in-process boot.
A TUI protocol timeout is undiagnosable when the two events that explain
it — bridge exit and response-send failure — are gated behind DSHX_DEBUG.
They now print unconditionally with a [dshx] prefix; debug-gated verbose
logging stays as-is.
Introduce a direct NDJSON stdio transport inside the already-mounted DSH composition, selected through the launcher's official cmdlineArgs service. Keep the legacy bridge as a migration fallback until the pinned Codex TUI is switched over.

Also fix presentation-row lifecycle ownership: plugin apply now completes after initialization and requests bounded host exit through appExit when the attached TUI or stdio client leaves, avoiding loader.await/readiness deadlock.
Switch the pinned Codex TUI to spawn the user's official dsh profile as a local NDJSON stdio app-server. Classify that child as a local backend so Codex remote-workspace semantics never leak into DSHX.

Remove the Unix-socket/WebSocket bridge, Node socket host and self-boot runtime helpers. Rework smoke and bundle verification to exercise only official dsh plugin/profile machinery, including initialize and bounded EOF/appExit shutdown.
Separate the compatible DSH peer range from the exact CI baseline, update ownership assertions for the official-host-only architecture, and move platform PTY gates to the stdio backend.
Package only the pinned TUI and standard DSH bundle, record the local stdio transport in provenance, and align release verification with the official-host-only runtime boundary.
Treat the underlying stdin end event as the authoritative stdio EOF signal, drain pending protocol work, then request the official DSH appExit. Keep readline close as a fallback and make the integration smoke expose the EOF/appExit stages with a bounded shutdown deadline.
@code-new-bie code-new-bie changed the title Refactor DSHX to native DSH stdio plugin surface Refactor DSHX to profile-owned Codex TUI surface Aug 28, 2026

Copy link
Copy Markdown
Owner Author

Final external-release handoff for exact candidate 3729f2a6e5dc6422a21875e86c64ebac3fb95297:

  • refactor/plugin-compliance-slim and release/1.0-rc both point to this exact SHA.
  • CI 33184987198, RC Platform Gate 33184987192, strict packaging preflight 33185259423, and four-platform release-matrix preflight 33185304658 are green on this candidate.
  • Current repository RC tags stop at v1.0.0-rc.8; there is no v1.0.0-rc.9 yet. rc.8 is the retired-architecture SHA and must not be reused.
  • The connected GitHub capability exposes branch refs but no Git-tag creation action, and no installable tag/release plugin is available. Do not emulate a tag with a branch or weaken the release contract.

The next external action is therefore exactly:

git fetch origin release/1.0-rc
git tag v1.0.0-rc.9 3729f2a6e5dc6422a21875e86c64ebac3fb95297
git push origin v1.0.0-rc.9

That tag must trigger the repository's existing Release workflow. Only after its four platform jobs, clean installs, provenance aggregation, SHA256SUMS, and prerelease creation succeed may #13–#15 be closed under their exact-RC/tag rules. Then fill #12 with the generated rc.9 Windows artifact/checksum and run the packaged Windows acceptance helper plus the real Windows Terminal side-by-side/Chinese IME compose-commit-cancel checklist. ConPTY evidence is not a substitute for that human gate.

Keep this PR draft and do not merge/promote stable v1.0.0 until those formal blockers are genuinely satisfied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant